﻿#region Using Statements
using System;
using System.Threading;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
#endregion

namespace BubbleSurvival
{
    /// <summary>
    /// This screen implements the actual game logic. It is just a
    /// placeholder to get the idea across: you'll probably want to
    /// put some more interesting gameplay in here!
    /// </summary>
    class GameplayScreen : GameScreen
    {
        #region Fields

        ContentManager content;
        SpriteFont gameFont;
        SpriteBatch spriteBatch;

        CameraManager cameraManager;
        DeveloperInterfaceManager devInterfaceManager;

        RenderTarget2D mainScene;
        RenderTarget2D lightMaskScene;
        Effect lightingEffect;

        MouseState prevMouse;
        KeyboardState prevKeyb;

        LightSource flare;
        List<LightSource> listOfLights;
        Texture2D dotTest;
        Random random;

        bool isNight;

        float pauseAlpha;

        #endregion

        #region Initialization

        public GameplayScreen()
        {
            TransitionOnTime = TimeSpan.FromSeconds(1.5);
            TransitionOffTime = TimeSpan.FromSeconds(0.5);
        }

        public override void LoadContent()
        {
            if (content == null)
                content = new ContentManager(ScreenManager.Game.Services, "Content");

            spriteBatch = ScreenManager.SpriteBatch;

            gameFont = content.Load<SpriteFont>(@"InGame\Fonts\gamefont");

            cameraManager = new CameraManager();

            devInterfaceManager = new DeveloperInterfaceManager(content.Load<SpriteFont>(@"InGame\Fonts\smallFont"));

            ScreenManager.Game.ResetElapsedTime();

            prevMouse = new MouseState();
            prevKeyb = new KeyboardState();

            flare = new LightSource(content.Load<Texture2D>(@"Test\dot"),
                                    new Vector2(300, 300),
                                    new Point(20,20),
                                    content.Load<Texture2D>(@"InGame\Textures\Light\lightmask"));

            dotTest = content.Load<Texture2D>(@"Test\dot");

            lightingEffect = content.Load<Effect>(@"Effects\\lighting");

            listOfLights = new List<LightSource>();

            random = new Random();

            for (int i = 0; i < 10; i++)
            {
                listOfLights.Add(new LightSource(content.Load<Texture2D>(@"Test\dot"),
                                                 new Vector2(random.Next(0, 2000), random.Next(0, 2000)),
                                                 new Point(20,20),
                                                 content.Load<Texture2D>(@"InGame\Textures\Light\lightmask")));
            }
            listOfLights[0].LightColor = Color.Yellow;
            listOfLights[2].LightColor = Color.Green;
            listOfLights[3].LightColor = Color.Red;
            listOfLights[4].LightColor = Color.Purple;

            var pp = ScreenManager.Game.GraphicsDevice.PresentationParameters;
            mainScene = new RenderTarget2D(ScreenManager.Game.GraphicsDevice, pp.BackBufferWidth, pp.BackBufferHeight);
            lightMaskScene = new RenderTarget2D(ScreenManager.Game.GraphicsDevice, pp.BackBufferWidth, pp.BackBufferHeight);

            isNight = true;
        }


        public override void UnloadContent()
        {
            content.Unload();
        }


        #endregion

        #region Update and Draw

        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
                                                       bool coveredByOtherScreen)
        {
            base.Update(gameTime, otherScreenHasFocus, false);

            // Gradually fade in or out depending on whether we are covered by the pause screen.
            if (coveredByOtherScreen)
                pauseAlpha = Math.Min(pauseAlpha + 1f / 32, 1);
            else
                pauseAlpha = Math.Max(pauseAlpha - 1f / 32, 0);

            if (IsActive)
            {

                flare.Position = get_mouse_vpos();
                cameraManager.Update(gameTime);
                devInterfaceManager.Update(gameTime);

            }

        }

        public override void HandleInput(InputState input)
        {
            if (input == null)
                throw new ArgumentNullException("input");

            KeyboardState keyboardState = input.CurrentKeyboardState;
            MouseState mouseState = input.CurrentMouseState;

            if (input.IsPauseGame())
            {
                ScreenManager.AddScreen(new PauseMenuScreen());
            }

            mouseState = Mouse.GetState();
            if (mouseState.LeftButton == ButtonState.Pressed && prevMouse.LeftButton == ButtonState.Released)
            {
                flare.Scale += 0.1f;
            }
            if (mouseState.RightButton == ButtonState.Pressed && prevMouse.RightButton == ButtonState.Released)
            {
                if (flare.Scale > 0.5f)
                {
                    flare.Scale -= 0.1f;
                }
            }
            keyboardState = Keyboard.GetState();
            if (keyboardState.IsKeyDown(Keys.N) && prevKeyb.IsKeyUp(Keys.N))
            {
                isNight ^= isNight;
            }

            prevMouse = mouseState;
            prevKeyb = keyboardState;

        }

        public override void Draw(GameTime gameTime)
        {
               
            drawNormalWithCamera();
            if (isNight)
            {
                drawNightWithCamera(gameTime);
            }
            drawMisc();

            ScreenManager.GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
            lightingEffect.Parameters["lightMask"].SetValue(lightMaskScene);
            lightingEffect.CurrentTechnique.Passes[0].Apply();
            spriteBatch.Draw(mainScene, new Vector2(0, 0), Color.White);
            spriteBatch.End();

        }

        private void drawNormalWithCamera()
        {
            ScreenManager.GraphicsDevice.SetRenderTarget(mainScene);
            ScreenManager.GraphicsDevice.Clear(Color.White);

            spriteBatch.Begin(SpriteSortMode.FrontToBack,
                                    BlendState.AlphaBlend,
                                    null,
                                    null,
                                    null,
                                    null,
                                    cameraManager.CreateTransformatedMatrix(ScreenManager.GraphicsDevice)
                                    );

            spriteBatch.Draw(dotTest, new Vector2(1030, 1210), null, Color.White, 0f, new Vector2(10,10), 0f, SpriteEffects.None, 0.1f);
            spriteBatch.Draw(dotTest, new Vector2(1220, 1030), null, Color.White, 0f, new Vector2(10, 10), 0f, SpriteEffects.None, 0.1f);
            spriteBatch.Draw(dotTest, new Vector2(1120, 1160), null, Color.White, 0f, new Vector2(10, 10), 0f, SpriteEffects.None, 0.1f);
            spriteBatch.Draw(dotTest, new Vector2(1300, 1090), null, Color.White, 0f, new Vector2(10, 10), 0f, SpriteEffects.None, 0.1f);
            spriteBatch.Draw(dotTest, new Vector2(1400, 1300), null, Color.White, 0f, new Vector2(10, 10), 0f, SpriteEffects.None, 0.1f);
            spriteBatch.Draw(dotTest, new Vector2(1490, 1120), null, Color.White, 0f, new Vector2(10, 10), 0f, SpriteEffects.None, 0.1f);
            spriteBatch.Draw(dotTest, new Vector2(1500, 1040), null, Color.White, 0f, new Vector2(10, 10), 0f, SpriteEffects.None, 0.1f);

            spriteBatch.End();

            ScreenManager.GraphicsDevice.SetRenderTarget(null);
        }

        private void drawNightWithCamera(GameTime gameTime)
        {
            ScreenManager.GraphicsDevice.SetRenderTarget(lightMaskScene);
            ScreenManager.GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin(SpriteSortMode.Immediate,
                        BlendState.Additive,
                        null,
                        null,
                        null,
                        null,
                        cameraManager.CreateTransformatedMatrix(ScreenManager.GraphicsDevice)
                        );

            flare.Draw(gameTime, spriteBatch);

            foreach (var light in listOfLights)
            {
                light.Draw(gameTime, spriteBatch);
            }

            spriteBatch.End();

            ScreenManager.GraphicsDevice.SetRenderTarget(null);

        }

        private void drawMisc()
        {
            // transitioning on or off, fade
            if (TransitionPosition > 0 || pauseAlpha > 0)
            {
                float alpha = MathHelper.Lerp(1f - TransitionAlpha, 1f, pauseAlpha / 2);

                ScreenManager.FadeBackBufferToBlack(alpha);
            }

            spriteBatch.Begin();

            if (GameOptionsMenuScreen.DevUI)
            {
                devInterfaceManager.Draw(spriteBatch, cameraManager.Pos, cameraManager.Zoom, get_mouse_vpos());
            }

            spriteBatch.End();
        }

        #endregion

        /// <summary>
        /// Egér koordináták kiszámolása (world).
        /// </summary>
        public Vector2 get_mouse_vpos()
        {
            Vector2 mp = new Vector2(
                        Mouse.GetState().X - ScreenManager.Game.GraphicsDevice.Viewport.Width * 0.5f,
                        Mouse.GetState().Y - ScreenManager.Game.GraphicsDevice.Viewport.Height * 0.5f);
            return mp * (1 / cameraManager.Zoom) + cameraManager.Pos;
        }

    }
}
